package com.example.base.service;

import com.example.base.entity.*;
import com.example.base.exception.GlobalException;
import com.example.base.mapper.*;
import com.example.base.vo.RespBeanEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class DormitoryService {

    @Autowired
    BuildingMapper buildingMapper;

    @Autowired
    UnitMapper unitMapper;

    @Autowired
    RoomMapper roomMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    UserDormRelationMapper userDormRelationMapper;

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    public void cacheRelation(String studentNo, UserDormRelation relation) {
        redisTemplate.opsForValue().set("no2relation:" + studentNo, relation);
    }

    public void cacheBuilding(Building building) {
        redisTemplate.opsForValue().set("BuildingName:" + building.getName(), building);
    }

    public void cacheUnit(Unit unit) {
        redisTemplate.opsForValue().set("unitId:" + unit.getId(), unit);
    }

    public List<Building> getAllBuilding() {
        return buildingMapper.getAllBuildings();
    }

    public List<Unit> getAllUnits() {
        return unitMapper.getAllUnits();
    }

    public Integer getIdByBuildingName(String name) {
        Building building = (Building) redisTemplate.opsForValue().get("BuildingName:" + name);
        if (building == null) return null;
        return building.getId();
    }

    public List<Integer> getUnitsByBuildingId(Integer buildingId) {
        Set<String> keys = redisTemplate.keys("unitId:*");
        if (keys == null) return null;
        List<Integer> res = new ArrayList<>();
        for (String key : keys) {
            Unit unit = (Unit) redisTemplate.opsForValue().get(key);
            if (unit != null && Objects.equals(unit.getBuildingId(), buildingId)) {
                res.add(unit.getId());
            }
        }
        return res;
    }

    public Unit getUnitById(Integer id) {
        return unitMapper.getUnitById(id);
    }

    public Integer getUnitIdByRoomId(Integer id) {
        return roomMapper.getUnitIdByRoomId(id);
    }

    public Building getBuildingById(Integer id) {
        return buildingMapper.getBuildingById(id);
    }

    public List<Room> getRoomsByUnitIdAndGenderGreaterThanCount(Integer unit, Integer count, String gender) {
        Set<String> keys = redisTemplate.keys("RoomId:*");
        if (keys == null) return null;
        List<Room> rooms = new ArrayList<>();
        for (String key : keys) {
            Room room = (Room) redisTemplate.opsForValue().get(key);
            if (room != null && Objects.equals(room.getGender(), gender)
                    && room.getRemain() > count && Objects.equals(room.getUnitId(), unit)) {
                rooms.add(room);
            }
        }
        return rooms;
    }

    public void updateRoomRemainById(Integer id, Integer value) {
        roomMapper.updateRoomRemainById(id, value);
    }

    public void insertRelation(UserDormRelation relation) {
        userDormRelationMapper.insertRelation(relation);
    }

    public Map<Object, Object> getAllDormitory() {
        Map<Object, Object> res = new HashMap<>();
        List<Building> buildings = buildingMapper.getAllBuildings();
        List<Unit> units = unitMapper.getAllUnits();
        List<Room> rooms = roomMapper.getAllRooms();
        for (Building building : buildings) {
            Integer countMan = 0, countFe = 0;
            List<Integer> buildingUnits = new ArrayList<>();
            for (Unit unit : units) {
                if (Objects.equals(unit.getBuildingId(), building.getId())) {
                    buildingUnits.add(unit.getId());
                }
            }
            for (Integer unitId : buildingUnits) {
                for (Room room : rooms) {
                    if (Objects.equals(room.getUnitId(), unitId)) {
                        if (Objects.equals(room.getGender(), "男")) countMan += room.getRemain();
                        else countFe += room.getRemain();
                    }
                }
            }
            res.put(building.getName() + "男", countMan);
            res.put(building.getName() + "女", countFe);
        }
        return res;
    }

    public List<Room> getAllRooms() {
        return roomMapper.getAllRooms();
    }

    public void cacheRoom(Room room) {
        redisTemplate.opsForValue().set("RoomId:" + room.getId(), room);
    }

    public Room getRoomById(Integer roomId) {
        return roomMapper.getRoomById(roomId);
    }

    /**
     * 用户轮询选宿舍结果
     *
     * @param studentNo
     * @return 0：排队中，1成功，-1失败
     */
    public Integer getResult(String studentNo) {
        if (Boolean.TRUE.equals(redisTemplate.hasKey("no2relation" + studentNo))) {
            return ((UserDormRelation) Objects.requireNonNull(redisTemplate.opsForValue().get("no2relation"))).getRoomId();
        }
        UserInfo info = userInfoMapper.getInfoByStudentNo(studentNo);
        if (info==null) throw new GlobalException(RespBeanEnum.STUDENTNO_ERROR);
        System.out.println("info = " + info);
        UserDormRelation relation = userDormRelationMapper.getRelationByUid(info.getId());
        System.out.println("relation = " + relation);
        if (relation == null) return 0;
        if (!relation.getValid()) return -1;
        return relation.getRoomId();
    }
}
